﻿
// DcmFileEditorDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "DcmFileEditor.h"
#include "DcmFileEditorDlg.h"
#include "afxdialogex.h"
#include "Utilities.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

static TAGInfo gTags[] = {
	{_T("AccessionNumber"),				_T("0008,0050"), _T("SH")},
	{_T("Manufacturer"),				_T("0008,0070"), _T("LO")},
	{_T("InstitutionName"),				_T("0008,0080"), _T("LO")},
	{_T("InstitutionAddress"),			_T("0008,0081"), _T("ST")},
	{_T("PerformingPhysiciansName"),	_T("0008,1050"), _T("PN")},
	{_T("OperatorsName"),				_T("0008,1070"), _T("PN")},
	{_T("PatientsName"),				_T("0010,0010"), _T("PN")},
	{_T("PatientId"),					_T("0010,0020"), _T("LO")},
	{_T("PatientsBirthday"),			_T("0010,0030"), _T("DA")},
	{_T("PatientsSex"),					_T("0010,0040"), _T("CS")},
	{_T("PatientsAge"),					_T("0010,1010"), _T("AS")},
	{_T("PatientsWeight"),				_T("0010,1030"), _T("DS")},
	{_T("StudyId"),						_T("0020,0010"), _T("SH")},
	{_T("StudyInstanceUID"),			_T("0020,000D"), _T("UI")},
	{_T("SeriesInstanceUID"),			_T("0020,000E"), _T("UI")},
	{_T("SopInstanceUID"),				_T("0008,0018"), _T("UI")},
	{_T("PrivateMeasureObj"),			_T("5EA1,1100"), _T("LT")}
};


// 顺序不能变
static const TCHAR* gVrs[] = {
	_T("AE"), _T("AS"), _T("AT"), _T("CS"), _T("DA"), _T("DS"), _T("DT"),_T("FL"),
	_T("FD"), _T("IS"), _T("LO"), _T("LT"), _T("OB"), _T("OD"), _T("OF"), _T("OL"),
	_T("OV"), _T("OW"), _T("PN"), _T("SH"), _T("SL"), _T("SQ"), _T("SS"), _T("ST"),
	_T("SV"), _T("TM"), _T("UC"), _T("UI"), _T("UL"), _T("UR"), _T("US"), _T("UT"), _T("UV")
};

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CDcmFileEditorDlg 对话框



CDcmFileEditorDlg::CDcmFileEditorDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DCMFILEEDITOR_DIALOG, pParent)
	, m_search(_T(""))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON_EDIT);
	//m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDcmFileEditorDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_FILE, m_lstFile);
	DDX_Control(pDX, IDC_LIST_TAG, m_lstTag);
	DDX_Control(pDX, IDC_LIST_MODTAG, m_lstModTag);
	DDX_Text(pDX, IDC_EDIT_TAGID, m_TagId);
	DDX_Text(pDX, IDC_EDIT_VAL, m_Val);
	DDX_Control(pDX, IDC_COMBO_TAGS, m_cmbTAG);
	DDX_Control(pDX, IDC_COMBO_VRTEXT, m_cmbVR);
	DDX_CBString(pDX, IDC_COMBO_VRTEXT, m_TagVr);
	DDX_CBString(pDX, IDC_COMBO_TAGS, m_tagDesc);
	DDX_Control(pDX, IDC_COMBO_COMPRESS, m_cmbComp);
	DDX_Text(pDX, IDC_EDIT_QUALITY, m_quality);
	DDX_Text(pDX, IDC_EDIT_SEARCH, m_search);
}

BEGIN_MESSAGE_MAP(CDcmFileEditorDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_OPENFILE, &CDcmFileEditorDlg::OnBnClickedButtonOpenfile)
	ON_BN_CLICKED(IDC_BUTTON_OPENDIR, &CDcmFileEditorDlg::OnBnClickedButtonOpendir)
	ON_BN_CLICKED(IDC_BUTTON_DELFILE, &CDcmFileEditorDlg::OnBnClickedButtonDelfile)
	ON_BN_CLICKED(IDC_BUTTON_SAVE, &CDcmFileEditorDlg::OnBnClickedButtonSave)
	ON_BN_CLICKED(IDC_BUTTON_SAVEAS, &CDcmFileEditorDlg::OnBnClickedButtonSaveas)
	ON_BN_CLICKED(IDC_BUTTON_ADD, &CDcmFileEditorDlg::OnBnClickedButtonAdd)
	ON_BN_CLICKED(IDC_BUTTON_DEL, &CDcmFileEditorDlg::OnBnClickedButtonDel)
	ON_BN_CLICKED(IDC_BUTTON_MODALL, &CDcmFileEditorDlg::OnBnClickedButtonModall)
	ON_CBN_SELCHANGE(IDC_COMBO_TAGS, &CDcmFileEditorDlg::OnSelchangeComboTags)
	ON_NOTIFY(NM_CLICK, IDC_LIST_MODTAG, &CDcmFileEditorDlg::OnClickListModtag)
	ON_LBN_DBLCLK(IDC_LIST_FILE, &CDcmFileEditorDlg::OnDblclkListFile)
	ON_CBN_SELCHANGE(IDC_COMBO_COMPRESS, &CDcmFileEditorDlg::OnSelchangeComboCompress)
	ON_EN_CHANGE(IDC_EDIT_SEARCH, &CDcmFileEditorDlg::OnChangeEditSearch)
END_MESSAGE_MAP()


// CDcmFileEditorDlg 消息处理程序

BOOL CDcmFileEditorDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	DcmParser::RegistryCodecs();

	m_nListWidth = m_nDefWidth = m_lstFile.GetHorizontalExtent();

	// TODO: 在此添加额外的初始化代码
	for (int i = 0, n = sizeof(gTags) / sizeof(TAGInfo); i < n; i++)
	{
		CString desc;
		desc = gTags[i].tagDesc;
		m_cmbTAG.AddString(desc);
	}

	for (int i = 0, n = sizeof(gVrs) / sizeof(TCHAR*); i < n; i++)
	{
		m_cmbVR.AddString(gVrs[i]);
	}

	m_cmbComp.AddString(_T("原图格式"));
	m_cmbComp.AddString(_T("无压缩格式"));
	m_cmbComp.AddString(_T("JPEG有损压缩"));
	m_cmbComp.AddString(_T("JPEG无损压缩"));
	m_cmbComp.AddString(_T("RLE无损压缩"));
	m_cmbComp.SetCurSel(0);
	GetDlgItem(IDC_EDIT_QUALITY)->EnableWindow(FALSE);

	m_lstModTag.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_FLATSB);
	TCHAR *name[] = { _T("TagId"), _T("VR"), _T("Value"), _T("Description") };
	short size[] = { 90, 50, 180, 120 };
	for (int i = 0; i < sizeof(name) / sizeof(TCHAR *); i++)
	{
		m_lstModTag.InsertColumn(i, name[i], LVCFMT_LEFT, size[i]);
	}

	m_lstTag.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_FLATSB);
	TCHAR *colName[] = { _T("TagId"),_T("VR"),_T("VM"),_T("Length"),_T("TagDesc"),_T("Value") };
	short colW[] = { 100, 40, 40, 60, 200, 400 };
	for (int i = 0; i < sizeof(colName) / sizeof(TCHAR *); i++)
	{
		m_lstTag.InsertColumn(i, colName[i], LVCFMT_LEFT, colW[i]);
	}

	m_lstTag.AddEditableCol(5);

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CDcmFileEditorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CDcmFileEditorDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CDcmFileEditorDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CDcmFileEditorDlg::OnBnClickedButtonOpenfile()
{
	UpdateData();

	CString strFilter;
	strFilter = _T("DCM file(*.dcm;*.dic)|*.dcm;*.dic|All files(*.*)|*.*||");
	CFileDialog dlg(TRUE, NULL, NULL,
		OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT,
		strFilter, NULL);

	TCHAR *pszFile = new TCHAR[MAX_PATH * 500];
	memset(pszFile, 0, sizeof(TCHAR)*MAX_PATH * 500);
	dlg.m_ofn.lpstrFile = pszFile;
	dlg.m_ofn.nMaxFile = MAX_PATH * 500;
	dlg.m_ofn.lpstrFile[0] = '\0';

	//m_lstFile.ResetContent();
	//m_vecDcmFile.clear();

	if (dlg.DoModal() == IDOK)
	{
		CString strFile;
		POSITION pos = dlg.GetStartPosition();
		while (pos != NULL)
		{
			strFile = dlg.GetNextPathName(pos);
			m_vecDcmFile.push_back(strFile);
			m_lstFile.AddString(strFile);
			UpdateWidth(strFile);
		}

		CString txt;
		txt.Format(_T("DICOM文件  数量: %d"), m_lstFile.GetCount());
		GetDlgItem(IDC_STATIC_FILE)->SetWindowText(txt);
	}

	delete[] pszFile;
}


void CDcmFileEditorDlg::OnBnClickedButtonOpendir()
{
	UpdateData();

	CFolderPickerDialog dlg(m_lastDir);
	if (dlg.DoModal() == IDOK)
	{
		CString dir = dlg.GetPathName();
		m_lastDir = dir;

		if (m_lastDir.Right(1) != _T("\\"))
			m_lastDir += _T("\\");

		EnumFileInDir(m_lastDir, m_vecDcmFile, _T(".dcm"));
		for (int i = 0; i < m_vecDcmFile.size(); i++)
		{
			m_lstFile.AddString(m_vecDcmFile.at(i));
			UpdateWidth(m_vecDcmFile.at(i));
		}

		CString txt;
		txt.Format(_T("DICOM文件  数量: %d"), m_lstFile.GetCount());
		GetDlgItem(IDC_STATIC_FILE)->SetWindowText(txt);
	}
}

void CDcmFileEditorDlg::UpdateWidth(LPCTSTR lpszItem)
{
	CFont *pFont = m_lstFile.GetFont();
	CClientDC dc(this);
	dc.SelectObject(pFont);
	CSize sz = dc.GetTextExtent(lpszItem, _tcslen(lpszItem));
	sz.cx += (3 * ::GetSystemMetrics(SM_CXBORDER));
	if (sz.cx > m_nListWidth)
	{
		m_nListWidth = sz.cx + 10;
		m_lstFile.SetHorizontalExtent(m_nListWidth);
	}
}


int CDcmFileEditorDlg::AddTag(const PrvTag& tag)
{
	BOOL bExist = FALSE;
	int idx = -1;

	for (int i = 0; i < m_overrideTag.size(); i++)
	{
		PrvTag eTag = m_overrideTag.at(i);
		if (tag.e == eTag.e && tag.g == eTag.g)
		{
			bExist = TRUE;
			idx = i;
			break;
		}
	}

	if (bExist)
		m_overrideTag.at(idx) = tag;
	else
		m_overrideTag.push_back(tag);

	return m_overrideTag.size();
}

CString CDcmFileEditorDlg::GetTagDesc(CString strTag)
{
	CString desc;
	if (strTag.CompareNoCase(_T("0008,0050")) == 0)
		desc = _T("AccessionNumber");
	else if (strTag.CompareNoCase(_T("0008,0070")) == 0)
		desc = _T("Manufacturer");
	else if (strTag.CompareNoCase(_T("0008,0080")) == 0)
		desc = _T("InstitutionName");
	else if (strTag.CompareNoCase(_T("0008,0081")) == 0)
		desc = _T("InstitutionAddress");
	else if (strTag.CompareNoCase(_T("0008,1050")) == 0)
		desc = _T("PerformingPhysiciansName");
	else if (strTag.CompareNoCase(_T("0008,1070")) == 0)
		desc = _T("OperatorsName");
	else if (strTag.CompareNoCase(_T("0010,0010")) == 0)
		desc = _T("PatientsName");
	else if (strTag.CompareNoCase(_T("0010,0020")) == 0)
		desc = _T("PatientId");
	else if (strTag.CompareNoCase(_T("0010,0030")) == 0)
		desc = _T("PatientsBirthday");
	else if (strTag.CompareNoCase(_T("0010,0040")) == 0)
		desc = _T("PatientsSex");
	else if (strTag.CompareNoCase(_T("0010,1010")) == 0)
		desc = _T("PatientsAge");
	else if (strTag.CompareNoCase(_T("0010,1030")) == 0)
		desc = _T("PatientsWeight");
	else if (strTag.CompareNoCase(_T("0020,0010")) == 0)
		desc = _T("StudyId");
	else if (strTag.CompareNoCase(_T("0020,000D")) == 0)
		desc = _T("StudyInstanceUid");
	else if (strTag.CompareNoCase(_T("0020,000E")) == 0)
		desc = _T("SeriesInstanceUid");
	else if (strTag.CompareNoCase(_T("0008,0018")) == 0)
		desc = _T("SopInstanceUid");
	else if (strTag.CompareNoCase(_T("5EA1,1100")) == 0) {
		desc = _T("PrivateMeasureObj");
	}

	return desc;
}

int CDcmFileEditorDlg::GetVR(CString vrName)
{
	int vr;
	if (vrName.CompareNoCase(_T("AE")) == 0)
		vr = 0;
	else if (vrName.CompareNoCase(_T("AS")) == 0)
		vr = 1;
	else if (vrName.CompareNoCase(_T("AT")) == 0)
		vr = 2;
	else if (vrName.CompareNoCase(_T("CS")) == 0)
		vr = 3;
	else if (vrName.CompareNoCase(_T("DA")) == 0)
		vr = 4;
	else if (vrName.CompareNoCase(_T("DS")) == 0)
		vr = 5;
	else if (vrName.CompareNoCase(_T("DT")) == 0)
		vr = 6;
	else if (vrName.CompareNoCase(_T("FL")) == 0)
		vr = 7;
	else if (vrName.CompareNoCase(_T("FD")) == 0)
		vr = 8;
	else if (vrName.CompareNoCase(_T("IS")) == 0)
		vr = 9;
	else if (vrName.CompareNoCase(_T("LO")) == 0)
		vr = 10;
	else if (vrName.CompareNoCase(_T("LT")) == 0)
		vr = 11;
	else if (vrName.CompareNoCase(_T("OB")) == 0)
		vr = 12;
	else if (vrName.CompareNoCase(_T("OD")) == 0)
		vr = 13;
	else if (vrName.CompareNoCase(_T("OF")) == 0)
		vr = 14;
	else if (vrName.CompareNoCase(_T("OL")) == 0)
		vr = 15;
	else if (vrName.CompareNoCase(_T("OV")) == 0)
		vr = 16;
	else if (vrName.CompareNoCase(_T("OW")) == 0)
		vr = 17;
	else if (vrName.CompareNoCase(_T("PN")) == 0)
		vr = 18;
	else if (vrName.CompareNoCase(_T("SH")) == 0)
		vr = 19;
	else if (vrName.CompareNoCase(_T("SL")) == 0)
		vr = 20;
	else if (vrName.CompareNoCase(_T("SQ")) == 0)
		vr = 21;
	else if (vrName.CompareNoCase(_T("SS")) == 0)
		vr = 22;
	else if (vrName.CompareNoCase(_T("ST")) == 0)
		vr = 23;
	else if (vrName.CompareNoCase(_T("SV")) == 0)
		vr = 24;
	else if (vrName.CompareNoCase(_T("TM")) == 0)
		vr = 25;
	else if (vrName.CompareNoCase(_T("UC")) == 0)
		vr = 26;
	else if (vrName.CompareNoCase(_T("UI")) == 0)
		vr = 27;
	else if (vrName.CompareNoCase(_T("UL")) == 0)
		vr = 28;
	else if (vrName.CompareNoCase(_T("UR")) == 0)
		vr = 29;
	else if (vrName.CompareNoCase(_T("US")) == 0)
		vr = 30;
	else if (vrName.CompareNoCase(_T("UT")) == 0)
		vr = 31;
	else if (vrName.CompareNoCase(_T("UV")) == 0)
		vr = 32;
	else
		vr = -1;

	return vr;

}

void CDcmFileEditorDlg::EnumFileInDir(CString dir, std::vector<CString>& vec, LPCTSTR ext /*= NULL*/)
{
	CFileFind finder;

	if (dir[dir.GetLength() - 1] != _T('\\')) dir += _T("\\");

	if (finder.FindFile(dir + _T("*.*")))
	{
		BOOL bFind = FALSE;
		do
		{
			bFind = finder.FindNextFile();

			if (finder.IsDots())
				continue;
			else if (finder.IsDirectory())
			{
				CString strDir = finder.GetFilePath();
				strDir += _T("\\");
				EnumFileInDir(strDir, vec, ext);
			}
			else
			{
				CString fnext;
				CString fn = finder.GetFileName();
				int pos = fn.ReverseFind(_T('.'));
				if (pos != -1)
				{
					CString strExt = ext;
					fnext = fn.Mid(pos);
					if (fnext.CompareNoCase(strExt) == 0)
						vec.push_back(finder.GetFilePath());
				}
			}

		} while (bFind);
	}
}

std::vector<DcmTagInfo> CDcmFileEditorDlg::filterTags(CString searchText)
{
	std::vector<DcmTagInfo> vec;

	std::string text = searchText;
	text = toLowercase(text);

	for (int i=0; i < m_vecCurTags.size(); i++)
	{
		DcmTagInfo info = m_vecCurTags.at(i);
		if (toLowercase(info.TagId).find(text) != std::string::npos
			|| toLowercase(info.TagName).find(text) != std::string::npos
			|| toLowercase(info.Value).find(text) != std::string::npos) {
			vec.push_back(info);
		}
	}

	return vec;
}

void CDcmFileEditorDlg::OnBnClickedButtonDelfile()
{
	m_lstFile.ResetContent();
	m_lstFile.SetHorizontalExtent(m_nDefWidth);
	m_vecDcmFile.clear();

	CString txt;
	txt.Format(_T("DICOM文件  数量: 0"));
	GetDlgItem(IDC_STATIC_FILE)->SetWindowText(txt);
}

void CDcmFileEditorDlg::OnSelchangeComboCompress()
{
	// TODO: 在此添加控件通知处理程序代码
	int nIdx = m_cmbComp.GetCurSel();
	GetDlgItem(IDC_EDIT_QUALITY)->EnableWindow(nIdx == 2);
}

void CDcmFileEditorDlg::OnBnClickedButtonSave()
{
	if (!m_dcmParser.IsValid())
		return;

	UpdateData();

	int nRows = m_lstTag.GetItemCount();

	for (int i = 0; i < nRows; i++)
	{
		CString tagId, vrName, val;
		tagId = m_lstTag.GetItemText(i, 0);
		vrName = m_lstTag.GetItemText(i, 1);
		val = m_lstTag.GetItemText(i, 5);

		CString oldVal;
		oldVal = m_vecCurTags.at(i).Value.c_str();
		if (oldVal == val)  // 值无改变, 不需要修改
			continue;

		if (tagId.GetLength() != 11)  // 序列内部, 不支持修改
			continue;

		if (tagId.CompareNoCase(_T("(7FE0,0010)")) == 0) // 图像数据, 不支持修改
			continue;

		if (vrName.CompareNoCase(_T("SQ")) == 0)   // 序列, 不能修改
			continue;

		PrvTag tag;
		sscanf_s(tagId, "(%hx,%hx)", &tag.g, &tag.e);

		if (tag.g == 2)  // MeteInfo 不能修改
			continue;

		tag.vr = GetVR(vrName);
		tag.val = val;

		m_dcmTag.push_back(tag);

	}


	int compress = m_cmbComp.GetCurSel();

	if (m_dcmParser.Save(compress, m_quality, &m_dcmTag))
		MessageBox(_T("修改成功."));
	else
		MessageBox(_T("修改失败."));
}


void CDcmFileEditorDlg::OnBnClickedButtonSaveas()
{
	if (!m_dcmParser.IsValid())
		return;

	UpdateData();

	int nRows = m_lstTag.GetItemCount();

	for (int i = 0; i < nRows; i++)
	{
		CString tagId, vrName, val;
		tagId = m_lstTag.GetItemText(i, 0);
		vrName = m_lstTag.GetItemText(i, 1);
		val = m_lstTag.GetItemText(i, 5);

		CString oldVal;
		oldVal = m_vecCurTags.at(i).Value.c_str();
		if (oldVal == val)  // 值无改变, 不需要修改
			continue;

		if (tagId.GetLength() != 11)  // 序列内部, 不支持修改
			continue;

		if (tagId.CompareNoCase(_T("(7FE0,0010)")) == 0) // 图像数据, 不支持修改
			continue;

		if (vrName.CompareNoCase(_T("SQ")) == 0)   // 序列, 不能修改
			continue;

		PrvTag tag;
		sscanf_s(tagId, "(%hx,%hx)", &tag.g, &tag.e);

		if (tag.g == 2)  // MeteInfo 不能修改
			continue;

		tag.vr = GetVR(vrName);
		tag.val = val;

		m_dcmTag.push_back(tag);

	}

	CString dst = m_dcmParser.GetFilePath().c_str();
	int pos = dst.ReverseFind(_T('.'));
	dst.Insert(pos, _T("_m"));

	CFileDialog dlg(FALSE, NULL, dst, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		_T("DICOM文件(*.dcm)|*.dcm| All Files (*.*) |*.*||"), NULL);

	// 打开文件对话框的标题名
	dlg.m_ofn.lpstrTitle = _T("输入保存文件名");
	//dlg.m_ofn.lpstrFile = (LPSTR)(LPCTSTR)dst;

	if (dlg.DoModal() == IDOK)
	{
		CString FilePathName = dlg.GetPathName();     //路径名+文件名
		CString FileName = dlg.GetFileName();     //文件名
		INT  index = dlg.m_ofn.nFilterIndex;
		if (1 == index)
		{
			//FilePathName += _T(".dcm");
			BOOL bCover = TRUE;
			if (PathFileExists(FilePathName))
			{
				CString strQuery;
				strQuery.Format(_T("%s 已经存在，要替换掉吗?"), FilePathName);
				if (IDNO == ::MessageBox(NULL, strQuery, _T("文件覆盖"),
					MB_ICONQUESTION | MB_YESNO))
				{
					//保存操作
					bCover = FALSE;
				}
			}

			if (bCover)
			{
				UpdateData();
				int compress = m_cmbComp.GetCurSel();

				std::string dst = FilePathName;
				if (m_dcmParser.SaveAs(dst, compress, m_quality, &m_dcmTag))
					MessageBox(_T("修改成功."));
				else
					MessageBox(_T("修改失败."));
			}

		}
	}

}


void CDcmFileEditorDlg::OnBnClickedButtonAdd()
{
	UpdateData();

	if (m_TagId.IsEmpty() || m_TagVr.IsEmpty() || m_Val.IsEmpty())
	{
		MessageBox(_T("请正确输入要修改的内容"));
		return;
	}

	m_TagId.Replace(_T("，"), _T(","));

	std::vector<std::string> vec = Split(std::string(m_TagId), ",");

	if (vec.size() != 2)
	{
		MessageBox(_T("DICOM TAG 格式不正确!"));
		return;
	}

	int nVr = m_cmbVR.GetCurSel();

	PrvTag tag;
	tag.g = strtoul(vec.at(0).c_str(), NULL, 16);
	tag.e = strtoul(vec.at(1).c_str(), NULL, 16);
	tag.vr = nVr;
	tag.val = m_Val;

	int num = AddTag(tag);

	m_lstModTag.DeleteAllItems();
	for (int i = 0; i < m_overrideTag.size(); i++)
	{
		PrvTag tag = m_overrideTag.at(i);
		CString strTag;
		strTag.Format(_T("%04X,%04X"), tag.g, tag.e);

		CString strVal;
		strVal = tag.val.c_str();

		int col = 0;
		m_lstModTag.InsertItem(i, _T(""));

		m_lstModTag.SetItemText(i, col++, strTag);
		m_lstModTag.SetItemText(i, col++, gVrs[tag.vr]);
		m_lstModTag.SetItemText(i, col++, tag.val.c_str());
		m_lstModTag.SetItemText(i, col++, GetTagDesc(strTag));
	}
}


void CDcmFileEditorDlg::OnBnClickedButtonDel()
{
	UpdateData();

	if (m_TagId.IsEmpty() || m_TagVr.IsEmpty() || m_Val.IsEmpty())
	{
		MessageBox(_T("请选择要删除的项目"));
		return;
	}

	BOOL bExist = FALSE;

	int g, e;
	sscanf_s(m_TagId, "%x,%x", &g, &e);

	std::vector<PrvTag>::iterator itr = m_overrideTag.begin();
	for (; itr != m_overrideTag.end(); itr++)
	{
		if (e == itr->e && g == itr->g)
		{
			bExist = TRUE;
			break;
		}
	}

	if (bExist)
	{
		m_overrideTag.erase(itr);

		m_lstModTag.DeleteAllItems();
		for (int i = 0; i < m_overrideTag.size(); i++)
		{
			PrvTag tag = m_overrideTag.at(i);
			CString strTag;
			strTag.Format(_T("%04X,%04X"), tag.g, tag.e);

			CString strVal;
			strVal = tag.val.c_str();

			int col = 0;
			m_lstModTag.InsertItem(i, _T(""));

			m_lstModTag.SetItemText(i, col++, strTag);
			m_lstModTag.SetItemText(i, col++, gVrs[tag.vr]);
			m_lstModTag.SetItemText(i, col++, tag.val.c_str());
			m_lstModTag.SetItemText(i, col++, GetTagDesc(strTag));
		}

		m_TagId = _T("");
		m_TagVr = _T("");
		m_Val = _T("");
		UpdateData(FALSE);
	}

}


void CDcmFileEditorDlg::OnBnClickedButtonModall()
{
	int n = m_lstFile.GetCount();
	if (n <= 0 || m_overrideTag.size() <= 0)
		return;

	CString saveDir;
	CFolderPickerDialog dlg(m_lastDir);
	if (dlg.DoModal() == IDOK)
	{
		saveDir = dlg.GetPathName();
		if (saveDir.Right(1) != _T("\\"))
			saveDir += _T("\\");
	}

	if (saveDir.IsEmpty())
		return;

	UpdateData();

	int nOK = 0, nFailed = 0;

	for (int i = 0; i < n; i++)
	{
		CString fn;
		m_lstFile.GetText(i, fn);

		CString shortFn;
		shortFn = fn.Mid(fn.ReverseFind(_T('\\')) + 1);
		int pos = shortFn.ReverseFind(_T('.'));
		//shortFn.Insert(pos, _T("_m"));

		std::string dst;
		dst = saveDir + shortFn;

		DcmParser dcm;
		if (dcm.Open(std::string(fn)))
		{
			int compress = m_cmbComp.GetCurSel();

			if (dcm.SaveAs(dst, compress, m_quality, &m_overrideTag))
				nOK++;
			else
				nFailed++;

		}
		else
		{
			nFailed++;
		}
	}

	CString msg;
	msg.Format(_T("总数:%d, 成功:%d, 失败:%d"), n, nOK, nFailed);
	MessageBox(msg);
}


void CDcmFileEditorDlg::OnSelchangeComboTags()
{
	// TODO: 在此添加控件通知处理程序代码
	int nIdx = m_cmbTAG.GetCurSel();
	TAGInfo tagInfo = gTags[nIdx];
	m_tagDesc = tagInfo.tagDesc;
	m_TagId = tagInfo.tagId;
	m_TagVr = tagInfo.tagVr;
	m_Val = _T("");

	UpdateData(FALSE);

}


void CDcmFileEditorDlg::OnClickListModtag(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码

	int idx = pNMItemActivate->iItem;

	UpdateData();

	m_TagId = m_lstModTag.GetItemText(idx, 0);
	m_TagVr = m_lstModTag.GetItemText(idx, 1);
	m_Val = m_lstModTag.GetItemText(idx, 2);
	m_tagDesc = m_lstModTag.GetItemText(idx, 3);

	UpdateData(FALSE);

	*pResult = 0;
}


void CDcmFileEditorDlg::OnDblclkListFile()
{
	CString str;
	int idx = m_lstFile.GetCurSel();
	m_lstFile.GetText(idx, str);

	if (m_dcmParser.Open(std::string(str)))
	{
		m_vecCurTags.clear();
		m_dcmParser.GetTagList(m_vecCurTags);

		m_lstTag.DeleteAllItems();

		int row = 0;

		std::vector<DcmTagInfo>::iterator itr = m_vecCurTags.begin();
		for (; itr != m_vecCurTags.end(); itr++)
		{
			int col = 0;
			m_lstTag.InsertItem(row, _T(""));

			m_lstTag.SetItemText(row, col++, itr->TagId.c_str());

			m_lstTag.SetItemText(row, col++, itr->vr.c_str());
			//   0           1         2         3            4            5     
			//{_T("TagId"),_T("VR"),_T("VM"),_T("Length"),_T("TagDesc"),_T("Value")}
			CString tmp;
			tmp.Format(_T("%d"), itr->vm);
			m_lstTag.SetItemText(row, col++, tmp);

			tmp.Format(_T("%d"), itr->Length);
			m_lstTag.SetItemText(row, col++, tmp);

			m_lstTag.SetItemText(row, col++, itr->TagName.c_str());

			m_lstTag.SetItemText(row, col++, itr->Value.c_str());

			row++;
		}
	}
}


void CDcmFileEditorDlg::OnChangeEditSearch()
{
	// TODO:  如果该控件是 RICHEDIT 控件，它将不
	// 发送此通知，除非重写 CDialogEx::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask()，
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

	// TODO:  在此添加控件通知处理程序代码
	UpdateData();
	std::vector<DcmTagInfo> vec = filterTags(m_search);

	m_lstTag.DeleteAllItems();

	int row = 0;

	std::vector<DcmTagInfo>::iterator itr = vec.begin();
	for (; itr != vec.end(); itr++)
	{
		int col = 0;
		m_lstTag.InsertItem(row, _T(""));

		m_lstTag.SetItemText(row, col++, itr->TagId.c_str());

		m_lstTag.SetItemText(row, col++, itr->vr.c_str());
		//   0           1         2         3            4            5     
		//{_T("TagId"),_T("VR"),_T("VM"),_T("Length"),_T("TagDesc"),_T("Value")}
		CString tmp;
		tmp.Format(_T("%d"), itr->vm);
		m_lstTag.SetItemText(row, col++, tmp);

		tmp.Format(_T("%d"), itr->Length);
		m_lstTag.SetItemText(row, col++, tmp);

		m_lstTag.SetItemText(row, col++, itr->TagName.c_str());

		m_lstTag.SetItemText(row, col++, itr->Value.c_str());

		row++;
	}
}
